package com.shi.yibanjia.aop;

import com.shi.yibanjia.annotation.Auth;
import com.shi.yibanjia.common.ResultCodeEnum;
import com.shi.yibanjia.entity.vo.SessionAccountVO;
import com.shi.yibanjia.enums.AuthCodeEnum;
import com.shi.yibanjia.enums.LogicalEnum;
import com.shi.yibanjia.exception.BusinessException;
import com.shi.yibanjia.util.UserContext;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;

import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

@Aspect
@Component
public class AuthAspect {

    @Pointcut("@annotation(com.shi.yibanjia.annotation.Auth)")
    public void pointCut() {
    }

    @Before(value = "pointCut()")
    public void handleBefore(JoinPoint joinPoint) {
        Method method = ((MethodSignature) joinPoint.getSignature()).getMethod();
        Auth annotation = method.getAnnotation(Auth.class);
        if (annotation == null || !annotation.requireAuth()) {
            return;
        }
        // 1. 校验是否登录
        checkLogin();
        // 2. 校验权限
        checkPerm(annotation);
    }

    private void checkLogin() {
        SessionAccountVO sessionAccountVO = UserContext.get();
        if (sessionAccountVO == null) {
            throw new BusinessException(ResultCodeEnum.NO_LOGIN, "未登录或登录过期");
        }
    }

    private void checkPerm(Auth annotation) {
        List<String> accountPerms = UserContext.getAuthority();
        AuthCodeEnum[] authCodeEnums = annotation.hasPerm();
        // hasPerm空数组的情况
        if (authCodeEnums == null || authCodeEnums.length == 0) {
            return;
        }
        LogicalEnum logical = annotation.logical();
        ArrayList<AuthCodeEnum> codeList = new ArrayList<>(Arrays.asList(authCodeEnums));
        // 逻辑或，逻辑与处理
        if (logical == LogicalEnum.OR) {
            if (codeList.contains(AuthCodeEnum.NO_NEED_PERM)) {
                return;
            }
            if (accountPerms == null || accountPerms.isEmpty()) {
                throw new BusinessException(ResultCodeEnum.NO_PERM);
            }
            // 是否存在一个权限码在用户的权限列表中
            for (AuthCodeEnum codeEnum : codeList) {
                if (accountPerms.contains(codeEnum.getCode())) {
                    return;
                }
            }
        } else {
            for (AuthCodeEnum codeEnum : codeList) {
                if (codeEnum == AuthCodeEnum.NO_NEED_PERM) {
                    continue;
                }
                if (!accountPerms.contains(codeEnum.getCode())) {
                    throw new BusinessException(ResultCodeEnum.NO_PERM);
                }
            }
        }
    }
}
